unit io_ImageCapture_Windows;

{
  Implements key simulation and screen capturing for windows.
}

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Controls, Graphics, io_imagecapture_basic,  SystemManager, Windows,
  io_imagecapture_const, io_ImageCapture_Windows_output;

type

  { TIO_ImageCapture_Windows }
  TIO_ImageCapture_Windows = class (TIO_ImageCapture_basic)
    private
      FWindowDC: HDC;
      FWindowHandle: Hwnd;
    protected
      procedure TakeScreenshoot(AImg: Graphics.TBitmap); override;
      procedure CreateOutput; override;
    public
      constructor Create; override;
      destructor Destroy; override;
    public
      property WindowHandle: Hwnd read FWindowHandle write FWindowHandle;
      property WindowDC: HDC read FWindowDC write FWindowDC;
  end;

const
  ClientWindowClass  = 'SunAwtFrame';
  ClientWindowTitle  = 'BrettspielWelt - Brettspiele Online Portal';

implementation

{ TIO_ImageCapture_Windows }

constructor TIO_ImageCapture_Windows.Create;
var
  buf: array[0..127] of AnsiChar;
  buf2: AnsiString;
  Style,ExStyle: long;
begin
  inherited Create;

  WindowDC := 0;
  //get the WindowHandle by window class name
  WindowHandle := FindWindow(ClientWindowClass, nil);
  If WindowHandle = 0 then raise Exception.Create('Window with class name "SunAwtFrame" not found. Is the client running?');
  //get the title of that window
  GetWindowText(WindowHandle,@buf, high(buf)-1);
  buf2 := Trim(buf);
  if buf2 <> ClientWindowTitle then raise Exception.Create('Window found, but title is wrong ('+buf2+' should be '+ClientWindowTitle+') !');
  //get a drawing handle
  WindowDC := GetWindowDc(WindowHandle);
  //remove border
  Style := GetWindowLong(WindowHandle, GWL_STYLE);
  Style := Style and (not(WS_CAPTION or WS_THICKFRAME or WS_MINIMIZE or WS_MAXIMIZE or WS_SYSMENU));
  SetWindowLong(WindowHandle, GWL_STYLE,Style);
  ExStyle :=GetWindowLong(WindowHandle, GWL_EXSTYLE);
  ExStyle := ExStyle and (not(WS_EX_DLGMODALFRAME or WS_EX_CLIENTEDGE or WS_EX_STATICEDGE));
  SetWindowLong(WindowHandle, GWL_EXSTYLE,ExStyle);
  //set the size
  SetWindowPos(WindowHandle,HWND_TOPMOST,0,0,ClientWindowWidth,ClientWindowHeight,SWP_ASYNCWINDOWPOS {or SWP_NOMOVE});
  sleep(200);
  //force it to redraw all, including the border
  ShowWindowAsync(WindowHandle, SW_SHOWMINIMIZED);
  sleep(200);
  ShowWindowAsync(WindowHandle, SW_SHOWNORMAL);

  TIO_ImageCapture_Windows_Output(output).WindowHandle := self.WindowHandle;
end;

destructor TIO_ImageCapture_Windows.Destroy;
begin
  if WindowDC <> 0 then ReleaseDC(WindowHandle,WindowDC);
  inherited Destroy;
end;

procedure TIO_ImageCapture_Windows.TakeScreenshoot(AImg: Graphics.TBitmap);
var
  FullImg: Graphics.TBitmap;
  c: TCanvas;
  r: TRect;
begin
  FullImg := Graphics.TBitmap.Create;
  try
    FullImg.SetSize(ClientWindowWidth,ClientWindowHeight);
    c := TCanvas.Create;
    c.Handle := WindowDC;
    try
      r := Classes.Rect(0, 0, ClientWindowWidth,ClientWindowHeight);
      FullImg.Canvas.CopyRect(r, c, r);
    finally
      c.Free;
    end;
    AImg.Assign(FullImg);
  finally
    FullImg.Free;
  end;
end;

procedure TIO_ImageCapture_Windows.CreateOutput;
begin
  FOutput := TIO_ImageCapture_Windows_Output.Create;
end;

initialization
  {$if defined(windows)}
    GlobalSystemManager.RegisterIOSystem(TIO_ImageCapture_Windows);
  {$ifend}
end.

